package com.yangff.service.impl;


import cn.hutool.core.bean.BeanUtil;
import com.yangff.api.client.ProductClient;
import com.yangff.api.client.UserClient;
import com.yangff.entity.product.entity.vo.ProductVo;
import com.yangff.entity.transaction.entity.Transactionrecord;
import com.yangff.entity.transaction.entity.dto.TransactionrecordDTO;
import com.yangff.entity.transaction.entity.vo.TransactionrecordVo;
import com.yangff.entity.user.entity.User;
import com.yangff.entity.user.entity.UserAsset;
import com.yangff.entity.user.entity.dto.UserAssetDTO;
import com.yangff.entity.user.entity.dto.UserDTO;
import com.yangff.entity.user.entity.vo.UserAssetVo;
import com.yangff.entity.user.entity.vo.UserVo;
import com.yangff.entity.vo.ResultVo;
import com.yangff.mapper.TransactionrecordMapper;
import com.yangff.service.ITransactionrecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yangff.utils.MathUtil;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 * 存储用户的交易记录 服务实现类
 * </p>
 *
 * @author yangff
 * @since 2025-01-19
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class TransactionrecordServiceImpl extends ServiceImpl<TransactionrecordMapper, Transactionrecord> implements ITransactionrecordService {
    private final UserClient userClient;
    private final ProductClient productClient;


    @GlobalTransactional(rollbackFor = Exception.class)
    @Override
    public ResultVo saveTransactionrocord(TransactionrecordDTO transactionrecordDTO) throws NoSuchAlgorithmException {
        if(!checkProductExist(transactionrecordDTO) || !checkUserExist(transactionrecordDTO)) return ResultVo.custom("用户或产品不存在，无法交易");

        if(transactionrecordDTO.getAmount() == 0) return ResultVo.custom("交易金额不能为0");

        //如果为购买，判断用户资产是否充足
        UserVo user = userClient.getUserByAccount(transactionrecordDTO.getAccount());

        if(MathUtil.hashWithSHA256(transactionrecordDTO.getPaymentPassword()).equals(user.getPaymentPassword()) == false) return ResultVo.custom("支付密码错误，无法交易");

        if( (transactionrecordDTO.getAmount() > 0) && (user.getFluidMoney() < transactionrecordDTO.getAmount() )) return ResultVo.custom("用户资产不足，无法交易");


        String action = transactionrecordDTO.getAmount() > 0 ? "买入" : "卖出";

        UserAssetVo userAssetVo = null;

        //如果为卖出，判断用户是否有足够的产品卖出
        if(action.equals("卖出"))
        {
            userAssetVo = userClient.getAllUserAssetByAccount(transactionrecordDTO.getAccount()).stream().filter(
                    userAsset -> userAsset.getCode().equals(transactionrecordDTO.getCode())
            ).findFirst().get();


            if(userAssetVo.getAmount() < Math.abs(transactionrecordDTO.getAmount())) transactionrecordDTO.setAmount(-userAssetVo.getAmount());

        }



        //修改用户资产记录
        UserAssetDTO userAssetDTO = BeanUtil.copyProperties(transactionrecordDTO, UserAssetDTO.class);
        userClient.changeUserAssetAmount(userAssetDTO);


        UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);
        userDTO.setChangeMoney(transactionrecordDTO.getAmount());
        userClient.updateUserFluidMoneyByAccount(userDTO);


        //加上记录
        Transactionrecord transactionrecord = BeanUtil.copyProperties(transactionrecordDTO, Transactionrecord.class);
        transactionrecord.setTransactionType(action);
        transactionrecord.setTransactionDate(LocalDateTime.now());


        save(transactionrecord);
        return ResultVo.success();
    }

    public boolean checkProductExist(TransactionrecordDTO transactionrecordDTO) {
        return (productClient.getProductByCode(transactionrecordDTO.getCode()) != null);
    }

    public boolean checkUserExist(TransactionrecordDTO transactionrecordDTO) {
        return (userClient.getUserByAccount(transactionrecordDTO.getAccount()) != null);
    }
}
